package com.github.authcloud.server.configure.filter.zuul;

import com.github.authcloud.server.configure.checker.UserWhiteBlackList;
import com.github.authcloud.server.configure.properties.AuthCommonProperties;
import com.github.authcloud.server.configure.utils.IpUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author : zhaoxuan
 * @version : 1.0
 * @date : 2021/8/24 21:17
 * @description : ZuulWhileListFilter
 */
public class ZuulBlackListFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private UserWhiteBlackList userWhiteBlackList;

    @Resource
    private RouteLocator routeLocator;

    @Resource
    private AuthCommonProperties authCommonProperties;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext= RequestContext.getCurrentContext();
        HttpServletRequest contextRequest=currentContext.getRequest();
        String userIp = IpUtil.getIpAddress(contextRequest);
        String serviceName = getServiceName(routeLocator, contextRequest.getRequestURI());
        //在忽略校验的服务中时,直接放行
        if (authCommonProperties.getIgnoreBlackService().stream().anyMatch(serviceName::equalsIgnoreCase)) {
            return null;
        }
        //在黑名单内,拒绝
        if (userWhiteBlackList.isInBlackList(userIp)) {
            logger.warn("The IP[{}] address is in the blacklist", userIp);
            throw new ZuulException("The IP address is in the blacklist", 407, "The IP address is in the blacklist");
        }
        return null;
    }

    private String getServiceName(RouteLocator routeLocator, String requestURI) {
        List<Route> routeList = routeLocator.getRoutes();
        Route matchRoute = routeList.stream().filter(route -> requestURI.startsWith(route.getPrefix())).findFirst().orElse(null);
        if (matchRoute == null) {
            throw new RuntimeException("Failed to obtain zuul routing information");
        }
        return matchRoute.getLocation();
    }
}
